
#include "mpi_lib.h"
#include "mpi.h"
#include "mpi_sys.h"
#include "mpi_cmd.h"
#include "mpi_isp.h"
#include "mpi_vi.h"
#include "mpi_version.h"

int sgks_mpi_sys_InitFwParam(sgks_mpi_manager_s *mpi);


inline int sgks_mpi_sys_WaitDspStats(sgks_mdi_dsp_status_s *dsp_status)
{

    u8 *msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);

    sgks_mdi_dsp_status_s *pdsp_status	= msg_buf;

    memcpy(pdsp_status, dsp_status, sizeof(sgks_mdi_dsp_status_s));

    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_WAITDSPSTATUS, 0, sizeof(sgks_mdi_dsp_status_s), SGKS_ERR_SYS_WAIT_DSP_STATUS_ERR);

    return SGKS_SUCCESS;

}


//test
int sgks_mpi_sys_GetStats(u8 *status)
{

    *status = 1;

    return SGKS_SUCCESS;
}

static int sgks_mpi_sys_CmdSetDspTimerMode()
{

    sgks_dsp_cmd_vi_timer_mode_s dsp_cmd;
    memset(&dsp_cmd, 0, sizeof(dsp_cmd));

    dsp_cmd.cmd_code = SGKS_DSP_CMD_H264_ENC_USE_TIMER;


    mpi_cmd_hex(dsp_cmd, cmd_code);

    int ret = sgks_mpi_cmd_Send(&dsp_cmd, sizeof(sgks_dsp_cmd_vi_timer_mode_s));

    if (ret != SGKS_SUCCESS)
    {
        return SGKS_ERR_SYS_SET_DSP_TIMER_MODE_ERR;
    }


    return SGKS_SUCCESS;

}


static int sgks_mpi_sys_SetDspTimerMode(sgks_mpi_manager_s *mpi)
{
    int ret = -1;

    sgks_mpi_cmd_SetMode(mpi, SGKS_MDI_CMD_MODE_NORMAL_LOADING);

    Printf("sgks_mpi_sys_SetDspTimerMode s\n");
    ret = sgks_mpi_sys_CmdSetDspTimerMode();
    if (ret != SGKS_SUCCESS)
        return ret;

    sgks_mpi_dsp_status_s dsp_status;
    dsp_status.op_mode  	= -1;
    dsp_status.op_sub_mode	= SGKS_DSP_TIMER_MODE;
    dsp_status.state    	= -1;

    ret = sgks_mpi_sys_WaitDspStats(&dsp_status);
    if (ret != SGKS_SUCCESS)
        return ret;

    Printf("sgks_mpi_sys_SetDspTimerMode e\n");

//refresh_vi_for_mipi();

    return SGKS_SUCCESS;

}


static int sgks_mpi_sys_SetDspOpMode( sgks_mpi_manager_s *mpi, sgks_dsp_op_mode_e mode)
{

    sgks_dsp_cmd_reset_operation_s dsp_cmd;
    sgks_mpi_dsp_status_s dsp_status;

    u8 *msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);



    Printf("set dsp op mode 0x%x\n",mode);

    /************* set cmd mode *******************/
    sgks_mpi_cmd_SetMode(mpi, SGKS_MDI_CMD_MODE_NORMAL_LOADING);

    /************* wait cmdq empty and lock interrupt *******************/
    sgks_mdi_wait_completion_s *mdi_completion = msg_buf;

    mdi_completion->completion		= SGKS_COMPLETION_CMD_AVAIL_COMPL;
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_WAIT_COMPLETION, 0, sizeof(sgks_mdi_wait_completion_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

    /************* disable cvbs dma *******************/
    if (mode == SGKS_DSP_DECODE_MODE)
    {
        sgks_mpi_sys_ConfigCvbsDma(0);
    }
    else if (mode == SGKS_DSP_ENCODE_MODE)
    {
        sgks_mpi_sys_ConfigCvbsDma(1);
    }

    /************* mmap init data, set decode mode*******************/
    mpi->mpi_init_param.dsp_init_param.operation_mode = mode;
    sgks_mpi_sys_InitFwParam(mpi);

    /************* reset cmd *******************/
    dsp_cmd.cmd_code = SGKS_DSP_CMD_RESET_OPERATION;
    mpi_cmd_hex(dsp_cmd, cmd_code);
    int ret = sgks_mpi_cmd_Send(&dsp_cmd, sizeof(sgks_dsp_cmd_reset_operation_s));

    if (ret != SGKS_SUCCESS)
    {
        return SGKS_ERR_SYS_SET_DSP_TIMER_MODE_ERR;
    }

    /************* set cmd mode *******************/
    sgks_mpi_cmd_SetMode(mpi, SGKS_MDI_CMD_MODE_BUSY);

    /************* wait status *******************/
    dsp_status.op_mode  	= mode;
    dsp_status.op_sub_mode	= -1;
    dsp_status.state    	= -1;
    ret = sgks_mpi_sys_WaitDspStats(&dsp_status);
    if (ret != SGKS_SUCCESS)
        return ret;

    sgks_mpi_cmd_SetMode(mpi, SGKS_MDI_CMD_MODE_NORMAL_LOADING);

    return SGKS_SUCCESS;

}

int sgks_mpi_sys_DecToEnc()
{

    int ret 		= -1;
    sgks_mpi_dsp_status_s dsp_status;

    sgks_mpi_manager_s *mpi = mpi_get_managerHanle();
    memset(&dsp_status, 0, sizeof(sgks_mpi_dsp_status_s));
    sgks_mpi_sys_GetDspStats(&dsp_status);

    Printf("dsp_state.op_mode 0x%x,dsp_state.state 0x%x\n",dsp_status.op_mode,dsp_status.state);

    if (dsp_status.op_mode == SGKS_DSP_DECODE_MODE)
    {

        dsp_status.op_mode  	= -1;
        dsp_status.op_sub_mode	= -1;
        dsp_status.state    	= SGKS_ENC_IDLE_STATE;
        ret = sgks_mpi_sys_WaitDspStats(&dsp_status);
        if (ret != SGKS_SUCCESS)
            return ret;

#if 1
       mpi->mpi_vo_dev[0].video_setup.src = SGKS_VO_SRC_ENC;

        ret = sgks_mpi_sys_SendDefaultCmd(mpi);
        if (ret != SGKS_SUCCESS)
        {
            return ret;
        }
#endif
        
        sgks_mpi_sys_ResetDSP();

        ret = sgks_mpi_sys_SetDspOpMode(mpi, SGKS_DSP_ENCODE_MODE);
        if (ret != SGKS_SUCCESS)
            return ret;

        ret = sgks_mpi_isp_Enable(mpi);
        if (ret != SGKS_SUCCESS)
            return ret;

        ret = sgks_mpi_isp_Reset3A(mpi);
        if (ret != SGKS_SUCCESS)
            return ret;

    }


    return SGKS_SUCCESS;
}

int sgks_mpi_sys_EncToDec()
{
    int ret 		= -1;
    sgks_mpi_dsp_status_s dsp_status;

    sgks_mpi_manager_s *mpi = mpi_get_managerHanle();

    memset(&dsp_status, 0, sizeof(sgks_mpi_dsp_status_s));
    sgks_mpi_sys_GetDspStats(&dsp_status);

    Printf("dsp_state.op_mode 0x%x,dsp_state.state 0x%x\n",dsp_status.op_mode,dsp_status.state);

    if (dsp_status.op_mode == SGKS_DSP_ENCODE_MODE)
    {

        dsp_status.op_mode  	= -1;
        dsp_status.op_sub_mode	= -1;
        dsp_status.state    	= SGKS_ENC_IDLE_STATE;
        ret = sgks_mpi_sys_WaitDspStats(&dsp_status);
        if (ret != SGKS_SUCCESS)
            return ret;

        ret = sgks_mpi_isp_Disable(mpi);
        if (ret != SGKS_SUCCESS)
            return ret;


        ret = sgks_mpi_sys_SetDspTimerMode(mpi);
        if (ret != SGKS_SUCCESS)
            return ret;


        ret = sgks_mpi_sys_SetDspOpMode(mpi, SGKS_DSP_DECODE_MODE);
        if (ret != SGKS_SUCCESS)
            return ret;


    }



    return SGKS_SUCCESS;



}

int sgks_mpi_sys_GetDspStats(sgks_mpi_dsp_status_s *dsp_status)
{


    u8 *msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);

    sgks_mdi_dsp_status_s *pdsp_status  = msg_buf;

    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_GETDSPSTATUS, 0, sizeof(sgks_mdi_dsp_status_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

    memcpy(dsp_status, pdsp_status, sizeof(sgks_mdi_dsp_status_s));


    return SGKS_SUCCESS;
}

int sgks_mpi_mdi_cmd(u32 cmd, u8 *arg)
{
    Printf("sgks_mpi_mdi_cmd 0x%x\n",cmd);
    return SGKS_SUCCESS;
}

static inline CAPTURE_BUFFER_ID venc_get_capture_buffer_id(u8 source_buffer_id)
{
    CAPTURE_BUFFER_ID capBuffId;

    switch(source_buffer_id)
    {
        case 1:
            capBuffId = PREVIEW_C_BUFFER_ID;
            break;
        case 2:
            capBuffId = PREVIEW_B_BUFFER_ID;
            break;
        case 3:
            capBuffId = PREVIEW_A_BUFFER_ID;
            break;
        case 0:
        default:
            capBuffId = MAIN_BUFFER_ID;
            break;
    }
    return capBuffId;
}

static int sgks_mpi_sys_initParam(sgks_mpi_manager_s *mpi)
{

    //system_setup
    memset(&mpi->system_setup, 0, sizeof(sgks_system_setup_info_ex_t));
    mpi->system_setup.voA_osd_blend_enable        			= 0;
    mpi->system_setup.voB_osd_blend_enable        			= 1;
    mpi->system_setup.low_delay_cap_enable        			= 0;
    mpi->system_setup.coded_bits_interrupt_enable 			= 1;
    mpi->system_setup.audio_clk_freq              			= 12288000;



    //source_buff
    memset(mpi->system_source_buff, 0, sizeof(mpi->system_source_buff));
    mpi->system_source_buff[0].type									= SGKS_SOURCE_BUFFER_TYPE_ENCODE;
    mpi->system_source_buff[0].state 								= SGKS_SOURCE_BUFFER_STATE_IDLE;
    mpi->system_source_buff[0].format.id 							= MEDIA_MAIN_BUFFER;
    mpi->system_source_buff[0].format.width 						= 1920;
    mpi->system_source_buff[0].format.height 						= 1080;
    mpi->system_source_buff[0].format.input_width 					= 0;
    mpi->system_source_buff[0].format.input_height 					= 0;
    mpi->system_source_buff[0].format.input_offset_x 				= 0;
    mpi->system_source_buff[0].format.input_offset_y 				= 0;
    mpi->system_source_buff[0].format.deintlc_for_intlc_vi 			= 0;
    mpi->system_source_buff[0].format.intlc_scan 					= 0;
    mpi->system_source_buff[0].property.max_width 					= MAX_WIDTH_FOR_1ST;
    mpi->system_source_buff[0].property.max_height 					= MAX_HEIGHT_FOR_1ST;
    mpi->system_source_buff[0].property.max_zoom_in_factor 			= MAX_ZOOM_IN_FACTOR_FOR_1ST;
    mpi->system_source_buff[0].property.max_zoom_out_factor 		= MAX_ZOOM_OUT_FACTOR_FOR_1ST;
    mpi->system_source_buff[0].ref_count 							= 0;

    mpi->system_source_buff[1].type									= SGKS_SOURCE_BUFFER_TYPE_ENCODE;
    mpi->system_source_buff[1].state 								= SGKS_SOURCE_BUFFER_STATE_IDLE;
    mpi->system_source_buff[1].format.id 							= MEDIA_2ND_BUFFER;
    mpi->system_source_buff[1].format.width 						= 1280;
    mpi->system_source_buff[1].format.height 						= 720;
    mpi->system_source_buff[1].format.input_width 					= 1920;
    mpi->system_source_buff[1].format.input_height 					= 1080;
    mpi->system_source_buff[1].format.input_offset_x 				= 0;
    mpi->system_source_buff[1].format.input_offset_y 				= 0;
    mpi->system_source_buff[1].format.deintlc_for_intlc_vi 			= 0;
    mpi->system_source_buff[1].format.intlc_scan 					= 0;
    mpi->system_source_buff[1].property.max_width 					= MAX_WIDTH_FOR_2ND;
    mpi->system_source_buff[1].property.max_height 					= MAX_HEIGHT_FOR_2ND;
    mpi->system_source_buff[1].property.max_zoom_in_factor 			= MAX_ZOOM_IN_FACTOR_FOR_2ND;
    mpi->system_source_buff[1].property.max_zoom_out_factor 		= MAX_ZOOM_OUT_FACTOR_FOR_2ND;
    mpi->system_source_buff[1].ref_count 							= 0;

    mpi->system_source_buff[2].type									= SGKS_SOURCE_BUFFER_TYPE_OFF;
    mpi->system_source_buff[2].state 								= SGKS_SOURCE_BUFFER_STATE_IDLE;
    mpi->system_source_buff[2].format.id 							= MEDIA_3RD_BUFFER;
    mpi->system_source_buff[2].format.width 						= 1280;
    mpi->system_source_buff[2].format.height 						= 720;
    mpi->system_source_buff[2].format.input_width 					= 1920;
    mpi->system_source_buff[2].format.input_height 					= 1080;
    mpi->system_source_buff[2].format.input_offset_x 				= 0;
    mpi->system_source_buff[2].format.input_offset_y 				= 0;
    mpi->system_source_buff[2].format.deintlc_for_intlc_vi 			= 0;
    mpi->system_source_buff[2].format.intlc_scan 					= 0;
    mpi->system_source_buff[2].property.max_width 					= MAX_WIDTH_FOR_3RD;
    mpi->system_source_buff[2].property.max_height 					= MAX_HEIGHT_FOR_3RD;
    mpi->system_source_buff[2].property.max_zoom_in_factor 			= MAX_ZOOM_IN_FACTOR_FOR_3RD;
    mpi->system_source_buff[2].property.max_zoom_out_factor 		= MAX_ZOOM_OUT_FACTOR_FOR_3RD;
    mpi->system_source_buff[2].ref_count 							= 0;
    mpi->system_source_buff[2].preview_framerate_division_factor 	= 1;

    mpi->system_source_buff[3].type									= SGKS_SOURCE_BUFFER_TYPE_PREVIEW;
    mpi->system_source_buff[3].state 								= SGKS_SOURCE_BUFFER_STATE_IDLE;
    mpi->system_source_buff[3].format.id 							= MEDIA_4TH_BUFFER;
    mpi->system_source_buff[3].format.width 						= 800;
    mpi->system_source_buff[3].format.height 						= 480;
    mpi->system_source_buff[3].format.input_width 					= 1920;
    mpi->system_source_buff[3].format.input_height 					= 1080;
    mpi->system_source_buff[3].format.input_offset_x 				= 0;
    mpi->system_source_buff[3].format.input_offset_y 				= 0;
    mpi->system_source_buff[3].format.deintlc_for_intlc_vi 			= 0;
    mpi->system_source_buff[3].format.intlc_scan 					= 0;
    mpi->system_source_buff[3].property.max_width 					= MAX_WIDTH_FOR_4TH;
    mpi->system_source_buff[3].property.max_height 					= MAX_HEIGHT_FOR_4TH;
    mpi->system_source_buff[3].property.max_zoom_in_factor 			= MAX_ZOOM_IN_FACTOR_FOR_4TH;
    mpi->system_source_buff[3].property.max_zoom_out_factor 		= MAX_ZOOM_OUT_FACTOR_FOR_4TH;
    mpi->system_source_buff[3].ref_count 							= 0;
    mpi->system_source_buff[3].preview_framerate_division_factor 	= 1;


    //system resource_setup
    mpi->system_resource.main_source_buffer_max_width 				= 1920;
    mpi->system_resource.main_source_buffer_max_height 				= 1080;
    mpi->system_resource.second_source_buffer_max_width 			= 1280;
    mpi->system_resource.second_source_buffer_max_height 			= 720;
    mpi->system_resource.third_source_buffer_max_width 				= 1280;//720, SH-L
    mpi->system_resource.third_source_buffer_max_height 			= 720;//576,
    mpi->system_resource.fourth_source_buffer_max_width 			= 352;
    mpi->system_resource.fourth_source_buffer_max_height 			= 288;

    mpi->system_resource.vo_max_width 								= 720;
    mpi->system_resource.vo_max_height 								= 576;


    mpi->system_resource.stream_max_GOP_M[0] 						= 1;/*3*/
    mpi->system_resource.stream_max_GOP_M[1] 						= 0;/*3*/
    mpi->system_resource.stream_max_GOP_M[2] 						= 0;/*3*/
    mpi->system_resource.stream_max_GOP_M[3] 						= 0;/*1*/


    mpi->system_resource.stream_max_GOP_N[0]						= 25;/*255*/
    mpi->system_resource.stream_max_GOP_N[1]						= 0;/*255*/
    mpi->system_resource.stream_max_GOP_N[2]						= 0;/*255*/
    mpi->system_resource.stream_max_GOP_N[3]						= 0;/*255*/

    mpi->system_resource.stream_max_advanced_quality_model[0] 		= 7;
    mpi->system_resource.stream_max_advanced_quality_model[1] 		= 7;
    mpi->system_resource.stream_max_advanced_quality_model[2]		= 7;
    mpi->system_resource.stream_max_advanced_quality_model[3]		= 7;



    mpi->system_resource.stream_max_encode_size[0].width 			= 1920;
    mpi->system_resource.stream_max_encode_size[0].height 			= 1080;
    mpi->system_resource.stream_max_encode_size[1].width 			= 0; /*1280*/
    mpi->system_resource.stream_max_encode_size[1].height 			= 0; /*720*/
    mpi->system_resource.stream_max_encode_size[2].width 			= 0; /*1280*/
    mpi->system_resource.stream_max_encode_size[2].height 			= 0; /*720*/
    mpi->system_resource.stream_max_encode_size[3].width 			= 0; /*352*/
    mpi->system_resource.stream_max_encode_size[3].height 			= 0; /*288*/


    mpi->system_resource.MCTF_possible 								= 1;
    mpi->system_resource.max_num_encode_streams 					= 1;/*4*/
    mpi->system_resource.max_num_cap_sources 						= 2;/*3*/
    mpi->system_resource.total_memory_size 							= 1;
    mpi->system_resource.cavlc_max_bitrate 							= 1500000;



    //vin_global_info
    mpi->vin_global_info.cmdReadDly									= 0;
    mpi->vin_global_info.pipeline_id					     		= 0;
    mpi->vin_global_info.high_mega_pixel_enable						= 0;

    Printf("sgks_mpi_sys_initParam ok!\n");

    return SGKS_SUCCESS;

}


static int sgks_mpi_sys_SetDspBuffer(sgks_mpi_manager_s *mpi)
{
    CHECK_POINT_NULL_RETURN(mpi,SGKS_FAIL);
    sgks_fw_init_param_s *init_param = &mpi->mpi_init_param.dsp_init_param;
    u8 *bsb_user_addr = NULL;
    u8 *bs_desc_user_addr = NULL;
    sgks_mdi_mmap_s *mmap_info = NULL;
    sgks_dsp_buffer_config_s *dsp_buff_info  = NULL;


    u8 *msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);
    mmap_info = msg_buf;

    SGKS_MDI_DRV_CLEAN_DATABUFF();
    mmap_info->mmap_phy_start_addr = (u8 *)init_param->bsb_phy;
    mmap_info->mmap_phy_size       = (int)init_param->bsb_size;
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_MMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);
    bsb_user_addr = mmap_info->mmap_user_start_addr;

    SGKS_MDI_DRV_CLEAN_DATABUFF();
    mmap_info->mmap_phy_start_addr = (u8 *)init_param->bsb_desc_phy;
    mmap_info->mmap_phy_size       = (int)init_param->bsb_size;
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_MMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);
    bs_desc_user_addr = mmap_info->mmap_user_start_addr;

    SGKS_MDI_DRV_CLEAN_DATABUFF();
    dsp_buff_info  = msg_buf;
    dsp_buff_info->cmd_buff.default_cmd_buffer.buffer_addr  = init_param->default_config_ptr_phy;
    dsp_buff_info->cmd_buff.default_cmd_buffer.buffer_size  = init_param->default_config_size;
    dsp_buff_info->cmd_buff.normal_cmd_buffer.buffer_addr   = init_param->cmd_data_ptr_phy;
    dsp_buff_info->cmd_buff.normal_cmd_buffer.buffer_size   = init_param->cmd_data_size;

    dsp_buff_info->result_queue.dsp_result_queue_start      = init_param->result_queue_ptr_phy;
    dsp_buff_info->result_queue.dsp_result_queue_ptr        = init_param->result_queue_ptr_phy;
    dsp_buff_info->result_queue.dsp_result_queue_end        = (u8*)((u8*)init_param->result_queue_ptr_phy + init_param->result_queue_size);
    dsp_buff_info->result_queue.dsp_result_queue_size       = init_param->result_queue_size;

    dsp_buff_info->dsp2_info.dsp2_info_ptr                 = init_param->dsp2_info_ptr_phy;

    dsp_buff_info->bsb_info.bsb_phy_start      = (u8 *)(init_param->bsb_phy);
    dsp_buff_info->bsb_info.bsb_size           = init_param->bsb_size;
    dsp_buff_info->bsb_info.bsb_user_start     = bsb_user_addr;

    dsp_buff_info->bsb_info.bs_desc_phy_start  = (u8 *)(init_param->bsb_desc_phy);
    dsp_buff_info->bsb_info.bs_desc_size       = init_param->bsb_desc_size;
    dsp_buff_info->bsb_info.bs_desc_user_start = bs_desc_user_addr;

	dsp_buff_info->cap_info.cap_info_ptr  		= (u8 *)(init_param->DSP_buf_ptr_phy);
    dsp_buff_info->cap_info.cap_info_ptr_size   = init_param->DSP_buf_size;

    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_SETDSPBUFFER, 0, sizeof(sgks_dsp_buffer_config_s), SGKS_ERR_SYS_DRIVERIOCTLERR);


    Printf("sgks_mpi_sys_SetCmdBuffer ok!\n");

    return SGKS_SUCCESS;

}


int sgks_mpi_sys_InitFwParam(sgks_mpi_manager_s *mpi)
{
    CHECK_POINT_NULL_RETURN(mpi,SGKS_FAIL);

    u8 *msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);
    sgks_mdi_mmap_s *mmap_info = msg_buf;

    sgks_fw_init_param_s *fw_init_param = &mpi->mpi_init_param.dsp_init_param;
    u8 *fw_init_param_addr = (u8*)fw_init_param->dsp_init_data_phy;
    u32 fw_init_param_size  = fw_init_param->dsp_init_data_size;

    //update fw init param
    sgks_fw_init_param_dsp_s fw_init_param_dsp;
    memcpy((void*)&fw_init_param_dsp, (void*)fw_init_param, sizeof(sgks_fw_init_param_dsp_s));

    Printf("fw_init_param_dsp.default_config_ptr 0x%x,fw_init_param_dsp.default_config_size0x%x\n",fw_init_param_dsp.default_config_ptr,fw_init_param_dsp.default_config_size);

    //copy to mem
    //mmap
    mmap_info->mmap_phy_start_addr = fw_init_param_addr;
    mmap_info->mmap_phy_size       = fw_init_param_size;
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_MMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

    Printf("mmap 0x%x ---> 0x%x, size:%d\n",fw_init_param_addr, mmap_info->mmap_user_start_addr,mmap_info->mmap_user_size);


    memcpy(mmap_info->mmap_user_start_addr, &fw_init_param_dsp, sizeof(sgks_fw_init_param_dsp_s));

    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_UNMMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

    SGKS_MDI_DRV_CLEAN_DATABUFF()
    sgks_mdi_opt_d_cache_s *cache 		= msg_buf;
    cache->cache_type                	= SGKS_OPT_D_CACHE_CLAEN;
    cache->start                     	= mpi->mpi_init_param.dsp_init_param.dsp_init_data_phy;
    cache->size                      	= mpi->mpi_init_param.dsp_init_param.dsp_init_data_size;
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_OPT_D_CACHE, 0, sizeof(sgks_mdi_opt_d_cache_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

    Printf("Init Fw Param [op mode %d] ok\n",fw_init_param_dsp.operation_mode);



    return SGKS_SUCCESS;

}




int sgks_mpi_sys_GetFwVersion(sgks_mpi_manager_s *mpi, u8 *orce_addr)
{

    u8 *addr=NULL;
    sgks_fw_version_s version;
	
    /*! firmware version number. */
	u32    verNum;
	/*! firmware sub version number. */
	u32    verSubNum;
    u32    verThirdNum;
    u8    verType;
    u16    year;
    u8     month;
    u8     day;

    addr = (u8 *)(orce_addr + 0x20);
    version.edition_num 		= addr[0];
    version.edition_subnum 		= addr[1];
    version.edition_thirdnum 	= addr[2];
    version.edition_extraverion = addr[3];
    version.year[0] 			= addr[4];
    version.year[1] 			= addr[5];
    version.month 				= addr[6];
    version.day 				= addr[7];

    verNum      			= version.edition_num/16*10 + version.edition_num%16;
    verSubNum   			= version.edition_subnum/16*10 + version.edition_subnum%16,
    verThirdNum 			= version.edition_thirdnum/16*100 + (version.edition_thirdnum%16)*10 + (version.edition_extraverion>>4),
    verType     			= version.edition_extraverion&0x0F - 0x0D + 'D';

    year        			= version.year[0]/16*1000 + (version.year[0]%16)*100 + version.year[1]/16*10 + (version.year[1]%16);
    month       			= version.month/16*10 + (version.month%16),
    day         			= version.day/16*10 + (version.day%16);

#if 1
    Printf("=== firmware version: %u.%u.%u%c , build date: %u-%u-%u\n"
           ,verNum
           ,verSubNum
           ,verThirdNum
           ,verType
           ,year
           ,month
           ,day);
#endif

 	sprintf(mpi->fw_version, "%u.%u.%u%c %u-%u-%u"
           ,verNum
           ,verSubNum
           ,verThirdNum
           ,verType
           ,year
           ,month
           ,day);

	Printf("=mpi== firmware version: %s\n",mpi->fw_version);

    return SGKS_SUCCESS;

}


static int sgks_mpi_sys_LoadFw(sgks_mpi_manager_s *mpi)
{

    CHECK_POINT_NULL_RETURN(mpi,SGKS_FAIL);

    int i =0;
    sgks_fw_info_s *fw_info     = &mpi->mpi_init_param.fw_info;
    dsp_code_addr_s *code_addr  = mpi->mpi_init_param.fw_info.code_addr;
    char filename[256];
    u32 filelen = 0;
    FILE *fp = NULL;
    struct stat f_buf;

    sgks_fw_load_tag_t sub_file_tag;
    int tag_Length = sizeof(sgks_fw_load_tag_t);
    int sub_fileLength  = 0;
    int filepos = 0;

    u8 *msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);

    sgks_mdi_mmap_s *mmap_info 			= msg_buf;
    sgks_mdi_opt_d_cache_s *cache 			= msg_buf;
    sgks_mdi_decrpty_mem_data_s *decrpty 	= msg_buf;

    u8* mmap_addr = NULL;

    if (fw_info->fw_type == SGKS_MPI_FW_ENCRYPTION)
    {

        if (fw_info->fw_file_num != 1 || strlen(fw_info->fw_path[0]) <= 0)
        {
            Printf("fw file_num err :%d\n", fw_info->fw_file_num);
            return SGKS_FAIL;
        }

        if((fp = fopen(fw_info->fw_path[0], "rb")) == NULL)
        {
            ERR_PRINT("open %s failed.\n", filename);
            return SGKS_ERR_SYS_OPENFWFILEFAIL;
        }

        stat(fw_info->fw_path[0], &f_buf);
        filelen = f_buf.st_size;


        for(i = 0; i < 3; i++)
        {

            if(fread(&sub_file_tag, 1, tag_Length, fp) != tag_Length)
            {
                Printf("fread tag failed\n");
                return SGKS_ERR_SYS_OPENFWFILEFAIL;
            }

            filepos += tag_Length;

            sub_fileLength = sub_file_tag.offset - tag_Length;

            if (code_addr[i].dsp_code_start == NULL || code_addr[i].dsp_code_size < sub_fileLength)
            {
                fclose(fp);

                Printf("code mem err, i:%d addr:%x, mem size:%d, sub_fileLength:%d\n"
                       ,i
                       ,code_addr[i].dsp_code_start
                       ,code_addr[i].dsp_code_size
                       ,sub_fileLength);

                return SGKS_ERR_SYS_FWCODEMEMCONFIGERR;
            }

            //mmap
            mmap_info->mmap_phy_start_addr = code_addr[i].dsp_code_start;
            mmap_info->mmap_phy_size       = code_addr[i].dsp_code_size;
            SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_MMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

            if (mmap_info->mmap_user_size == code_addr[i].dsp_code_size && mmap_info->mmap_user_start_addr != NULL)
                mmap_addr = mmap_info->mmap_user_start_addr;

            Printf("mmap [%d] 0x%x --> 0x%x,  size:%d filelen %d\n"
					,i
					,(u32)code_addr[i].dsp_code_start
					,(u32)mmap_info->mmap_user_start_addr
					,mmap_info->mmap_user_size
					,sub_fileLength);

            if(fread(mmap_addr, 1, sub_fileLength, fp) != sub_fileLength)
            {
                fclose(fp);
                ERR_PRINT("fread failed\n");
                SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_UNMMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);
                return SGKS_ERR_SYS_READFWFILEFAIL;
            }

            filepos += sub_fileLength;

            SGKS_MDI_DRV_CLEAN_DATABUFF();
            cache 								= msg_buf;
            cache->cache_type                	= SGKS_OPT_D_CACHE_CLAEN;
            cache->start                     	= code_addr[i].dsp_code_start;
            cache->size                      	= code_addr[i].dsp_code_size;
            SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_OPT_D_CACHE, 0, sizeof(sgks_mdi_opt_d_cache_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

#if 1
            SGKS_MDI_DRV_CLEAN_DATABUFF();
            decrpty 							= msg_buf;
            decrpty->mode                		= SGKS_CRYPTO_DES;
#if 0
            sgks_crypto_key_s  test_deskey = {{0x44332211, 0x88776655}};
            memcpy(&decrpty->pkey, &test_deskey, sizeof(sgks_crypto_key_s));
#else
            decrpty->pkey.key[0] = 0x44332211;
            decrpty->pkey.key[1] = 0x88776655;
#endif
            decrpty->phy_mem_addr               = code_addr[i].dsp_code_start;
            decrpty->size						= sub_fileLength;
            SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_DECRYPT_MEM_DATA, 0, sizeof(sgks_mdi_decrpty_mem_data_s), SGKS_ERR_SYS_DRIVERIOCTLERR);
#endif
            if (i==0)
            {
                sgks_mpi_sys_GetFwVersion(mpi, mmap_addr);
            }

			
#if 0
			char test_filename[32] = {0};
			sprintf(test_filename, "/home/fw-%d.bin",i);
			FILE *test_fp = fopen(test_filename, "wb");
		    if (!test_fp)
		    {
		        Printf("write fw pfd err\n");
		        return -1;
		    }
			
			fwrite(mmap_addr,1,sub_fileLength,test_fp);
            fflush(test_fp);
			fclose(test_fp);
			
			Printf("write test_filename[%s] ok!\n",test_filename);

#endif

            //unmmap
            SGKS_MDI_DRV_CLEAN_DATABUFF();
            mmap_info->mmap_user_start_addr = mmap_addr;
            mmap_info->mmap_user_size = code_addr[i].dsp_code_size;
            SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_UNMMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

        }


        fclose(fp);

        if (filepos == filelen)
        {
            Printf("load ENCRYPTION fw ok!\n");
        }
        else
        {
            Printf("load ENCRYPTION fw err! filepos %d, filelen %d\n",filepos, filelen);
        }



    }
    else if (fw_info->fw_type == SGKS_MPI_FW_UNENCRYPTION)
    {
        for(i = 0; i < fw_info->fw_file_num; i++)
        {

        memset(msg_buf, 0, sizeof(sgks_mdi_mmap_s));

        if((fp = fopen(fw_info->fw_path[i], "rb")) == NULL)
        {
            ERR_PRINT("open %s failed.\n", filename);
            return SGKS_ERR_SYS_OPENFWFILEFAIL;
        }

        stat(fw_info->fw_path[i], &f_buf);
        filelen = f_buf.st_size;

        if (code_addr[i].dsp_code_start == NULL || code_addr[i].dsp_code_size < filelen)
        {
            fclose(fp);

            Printf("code mem err, i:%d addr:%x, mem size:%d, file len:%d\n"
                   ,i
                   ,code_addr[i].dsp_code_start
                   ,code_addr[i].dsp_code_size
                   ,filelen);

            return SGKS_ERR_SYS_FWCODEMEMCONFIGERR;
        }

        //mmap
        mmap_info->mmap_phy_start_addr = code_addr[i].dsp_code_start;
        mmap_info->mmap_phy_size       = code_addr[i].dsp_code_size;
        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_MMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

        if (mmap_info->mmap_user_size == code_addr[i].dsp_code_size && mmap_info->mmap_user_start_addr != NULL)
            mmap_addr = mmap_info->mmap_user_start_addr;

            Printf("mmap 0x%x --> 0x%x,  size:%d filelen 0x%x\n",(u32)code_addr[i].dsp_code_start, (u32)mmap_info->mmap_user_start_addr,mmap_info->mmap_user_size,filelen);

        if(fseek(fp, 0, SEEK_SET) < 0)
        {
            fclose(fp);
            ERR_PRINT("SEEK_SET failed\n");
            SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_UNMMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);
            return SGKS_ERR_SYS_SEEKFWFILEFAIL;
        }

        Printf("mmap_addr 0x%x,0x%x\n",mmap_addr,mmap_info->mmap_user_start_addr);

        if(fread(mmap_addr, 1, filelen, fp) != filelen)
        {
            fclose(fp);
            ERR_PRINT("fread failed\n");
            SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_UNMMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);
            return SGKS_ERR_SYS_READFWFILEFAIL;
        }

        fclose(fp);

        SGKS_MDI_DRV_CLEAN_DATABUFF();
        cache 								= msg_buf;
        cache->cache_type                	= SGKS_OPT_D_CACHE_CLAEN;
        cache->start                     	= code_addr[i].dsp_code_start;
        cache->size                      	= code_addr[i].dsp_code_size;
        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_OPT_D_CACHE, 0, sizeof(sgks_mdi_opt_d_cache_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

        if (i==0)
        {
            sgks_mpi_sys_GetFwVersion(mpi, mmap_addr);
        }

        SGKS_MDI_DRV_CLEAN_DATABUFF();
        mmap_info->mmap_user_start_addr = mmap_addr;
        mmap_info->mmap_user_size = code_addr[i].dsp_code_size;
        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_UNMMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

    }

        Printf("load UNENCRYPTION fw ok!\n");

    }

    memset(msg_buf, 0, sizeof(sgks_mdi_reg_rw_s));
    sgks_mdi_reg_rw_s *reg = msg_buf;
    reg->reg_num =3;

    reg->reg_info[0].addr 			= 0xf0004088;
    reg->reg_info[0].addr_type   	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    reg->reg_info[0].val  		 	= 0x10000C00;

    reg->reg_info[1].addr 			= 0xf0004048;
    reg->reg_info[1].addr_type   	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    reg->reg_info[1].val  		 	= 0x00000100;

    reg->reg_info[2].addr 			= 0xf115000c;
    reg->reg_info[2].addr_type   	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    reg->reg_info[2].val  		 	= 0x00000007;

    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_REG_WRITE, 0, sizeof(sgks_mdi_reg_rw_s), SGKS_ERR_SYS_DRIVERIOCTLERR);


    Printf("boot fw ok!\n");

    return SGKS_SUCCESS;

}




int sgks_mpi_sys_GetDriverHandle(sgks_mpi_manager_s *mpi)
{
    CHECK_POINT_NULL_RETURN(mpi,SGKS_FAIL);

    int ret;

    if((ret = open(MPI_DRIVER_MEDIA_DEV, O_RDWR, 0)) < 0)
    {
        Printf("err open mpi driver dev:%s\n", MPI_DRIVER_MEDIA_DEV);
        return SGKS_ERR_SYS_OPENDRIVERDEVERR;
    }

    mpi->driver_handle[mpi->curr_module_id] = ret;

    return SGKS_SUCCESS;

}


int sgks_mpi_sys_LoseDriverHandle(sgks_mpi_manager_s *mpi)
{
    CHECK_POINT_NULL_RETURN(mpi,SGKS_FAIL);

	int i = 0;
	for (i=0; i<MAX_MPI_MODULE_NUM; i++)
	{
	    if (mpi->driver_handle[i])
	    {
			close(mpi->driver_handle[i]);
			mpi->driver_handle[i] = -1;
		}
	}
	
	return SGKS_SUCCESS;

}


static int sgks_mpi_sys_Cmd_CapturePreviewSize(sgks_mpi_manager_s *mpi
        ,sgks_vi_src_capability_s *current_vi_info
        ,int buffer_id
        ,int pcap_width
        ,int pcap_height
        ,int pinput_win_offset_x
        ,int pinput_win_offset_y
        ,int pinput_win_width
        ,int pinput_win_height)
{

    sgks_dsp_cmd_ipcam_capture_preview_size_setup_s dsp_cmd;

    memset(&dsp_cmd, 0, sizeof(dsp_cmd));
    dsp_cmd.cmd_code 				= SGKS_DSP_CMD_IPCAM_VIDEO_CAPTURE_PREVIEW_SIZE_SETUP;
    dsp_cmd.capture_source 		= venc_get_capture_buffer_id(buffer_id);
    
    if(pcap_width == 0 && pcap_height == 0)
    {
        dsp_cmd.disabled = 1;

        switch(buffer_id)
        {

        case SGKS_ENCODE_SOURCE_SECOND_BUFFER:
            dsp_cmd.cap_width  = mpi->system_resource.second_source_buffer_max_width;
            dsp_cmd.cap_height = mpi->system_resource.second_source_buffer_max_height;
            break;

        case SGKS_ENCODE_SOURCE_THIRD_BUFFER:
            dsp_cmd.cap_width  = mpi->system_resource.third_source_buffer_max_width;
            dsp_cmd.cap_height = mpi->system_resource.third_source_buffer_max_height;
            break;

        case SGKS_ENCODE_SOURCE_FOURTH_BUFFER:
            dsp_cmd.cap_width  = mpi->system_resource.fourth_source_buffer_max_width;
            dsp_cmd.cap_height = mpi->system_resource.fourth_source_buffer_max_height;
            break;
        default:
            return -EINVAL;
            break;
        }
    }
    else
    {
        dsp_cmd.disabled     = 0;
        dsp_cmd.cap_width    = pcap_width;
        dsp_cmd.cap_height   = pcap_height;
    }

    if((current_vi_info->video_format == SGKS_VIDEO_FORMAT_PROGRESSIVE) && (mpi->system_source_buff[buffer_id].format.intlc_scan == INTLC_ON))
    {
        //progressive VI to interlaced field encoding
        dsp_cmd.output_scan_format = 1;
    }
    else if((current_vi_info->video_format == SGKS_VIDEO_FORMAT_INTERLACE) && (mpi->system_source_buff[buffer_id].format.deintlc_for_intlc_vi == DEINTLC_OFF))
    {
        //interlaced VI to interlaced field encoding
        dsp_cmd.output_scan_format = 1;
    }
    else
    {
        dsp_cmd.output_scan_format = 0;
    }

    dsp_cmd.deinterlace_mode 		= mpi->system_source_buff[buffer_id].format.deintlc_for_intlc_vi;

    dsp_cmd.input_win_offset_x 		= pinput_win_offset_x;
    dsp_cmd.input_win_offset_y 		= pinput_win_offset_y;
    dsp_cmd.input_win_width = pinput_win_width;
    dsp_cmd.input_win_height = pinput_win_height;
    
    Printf("input_win_width:%d,h:%d,x:%d,y:%d\n"
           ,dsp_cmd.input_win_width
           ,dsp_cmd.input_win_height
           , dsp_cmd.input_win_offset_x
           , dsp_cmd.input_win_offset_y);

    mpi_cmd_hex(dsp_cmd, cmd_code);
    mpi_cmd(dsp_cmd, capture_source);
    mpi_cmd(dsp_cmd, output_scan_format);
    mpi_cmd(dsp_cmd, deinterlace_mode);
    mpi_cmd(dsp_cmd, disabled);
    mpi_cmd(dsp_cmd, cap_width);
    mpi_cmd(dsp_cmd, cap_height);
    mpi_cmd(dsp_cmd, input_win_offset_x);
    mpi_cmd(dsp_cmd, input_win_offset_y);
    mpi_cmd(dsp_cmd, input_win_width);
    mpi_cmd(dsp_cmd, input_win_height);

    int ret = sgks_mpi_cmd_Send(&dsp_cmd, sizeof(sgks_dsp_cmd_ipcam_capture_preview_size_setup_s));
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }

    return SGKS_SUCCESS;


}



int sgks_mpi_sys_cmd_RgbGainDefault(sgks_mpi_manager_s *mpi)
{
    u8 input_format = 0;
    sgks_dsp_cmd_rgb_gain_adjust_s dsp_cmd;

    sgks_vi_src_capability_s vi_cap_ability[MAX_VI_NUM];
    sgks_vi_src_capability_s *current_vi_info  = NULL;

    int ret = sgks_mpi_vi_GetSensorCapability(vi_cap_ability);
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }

    current_vi_info = &vi_cap_ability[0];


    input_format = current_vi_info->input_format;
    if(input_format)
    {
        Printf("input_format err!\n");
        return SGKS_FAIL;
    }


    memset(&dsp_cmd, 0, sizeof(dsp_cmd));
    dsp_cmd.cmd_code 			= SGKS_DSP_CMD_RGB_GAIN_ADJUSTMENT;
    dsp_cmd.r_gain 				= 0x578 << 6;
    dsp_cmd.g_even_gain 		= 0x400 << 6;
    dsp_cmd.g_odd_gain 			= 0x400 << 6;
    dsp_cmd.b_gain 				= 0x6A4 << 6;
    dsp_cmd.group_index 		= 0x0;

    ret = sgks_mpi_cmd_Send(&dsp_cmd, sizeof(sgks_dsp_cmd_rgb_gain_adjust_s));
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }

}



int sgks_mpi_sys_cmd_CapturePreviewBufferSetup(sgks_mpi_manager_s *mpi)
{

    int cap_width, cap_height = 0;
    int input_win_width = 0, input_win_height = 0;
    int i = 0;
    sgks_vi_src_capability_s vi_cap_ability[MAX_VI_NUM];
    sgks_vi_src_capability_s *current_vi_info  = NULL;

    int ret = sgks_mpi_vi_GetSensorCapability(vi_cap_ability);
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }

    current_vi_info = &vi_cap_ability[0];

    //FW just only support 2 channel encode
    for(i = 0 ; i < 2; i++)
    {

        if(mpi->system_source_buff[i].type != SGKS_SOURCE_BUFFER_TYPE_ENCODE)
        {
            continue;
        }
    
        switch(i)
        {

        case SGKS_ENCODE_SOURCE_MAIN_BUFFER:
            cap_width  = mpi->system_source_buff[i].format.width;
            cap_height = mpi->system_source_buff[i].format.height;
            break;

        case SGKS_ENCODE_SOURCE_SECOND_BUFFER:

            if(mpi->system_resource.second_source_buffer_max_width == 0)
            {
                return 0;
            }

            cap_width = mpi->system_resource.second_source_buffer_max_width;
            cap_height = mpi->system_resource.second_source_buffer_max_height;
            break;


        case SGKS_ENCODE_SOURCE_THIRD_BUFFER:

            if(mpi->system_resource.third_source_buffer_max_width == 0)
            {
                return 0;
            }

            cap_width = mpi->system_resource.third_source_buffer_max_width;
            cap_height = mpi->system_resource.third_source_buffer_max_height;
            break;


        case SGKS_ENCODE_SOURCE_FOURTH_BUFFER:

            if(mpi->system_resource.fourth_source_buffer_max_width == 0)
            {
                return 0;
            }

            cap_width  = mpi->system_resource.fourth_source_buffer_max_width;
            cap_height = mpi->system_resource.fourth_source_buffer_max_height;
            break;


        default:
            return -EINVAL;
            break;


        }

        input_win_width  = mpi->system_source_buff[0].format.width;
        input_win_height = mpi->system_source_buff[0].format.height;

        sgks_mpi_sys_Cmd_CapturePreviewSize(mpi, current_vi_info, i, cap_width, cap_height, 0, 0, input_win_width, input_win_height);

    }

    return SGKS_SUCCESS;

}



int sgks_mpi_sys_Cmd_SetupInfo(sgks_mpi_manager_s *mpi)
{


    sgks_dsp_cmd_system_setup_info_s     dsp_cmd;

    memset(&dsp_cmd, 0, sizeof(dsp_cmd));

    dsp_cmd.cmd_code                        =  SGKS_DSP_CMD_SYSTEM_SETUP_INFO;
    dsp_cmd.preview_A_type 					=  mpi->preview_config.preview_info[SGKS_VO_PREVIEW_A].pre_type;
    dsp_cmd.preview_B_type 					=  mpi->preview_config.preview_info[SGKS_VO_PREVIEW_B].pre_type;
    dsp_cmd.sub_mode_sel.multiple_stream 	=  SGKS_IPCAM_APP_MODE;
    dsp_cmd.sub_mode_sel.power_mode      	=  0;
    dsp_cmd.voA_osd_blend_enabled 			=  mpi->system_setup.voA_osd_blend_enable;
    dsp_cmd.voB_osd_blend_enabled 			=  mpi->system_setup.voB_osd_blend_enable;
    dsp_cmd.coded_bits_interrupt_enabled 	=  mpi->system_setup.coded_bits_interrupt_enable;
    dsp_cmd.pip_size_preview_enabled 		=  mpi->system_setup.pip_size_enable;
    dsp_cmd.audio_clk_freq 					=  mpi->system_setup.audio_clk_freq;
    dsp_cmd.low_delay_enabled 				=  1;

    mpi_cmd_hex(dsp_cmd, cmd_code);
    mpi_cmd(dsp_cmd, preview_A_type);
    mpi_cmd(dsp_cmd, preview_B_type);
    mpi_cmd(dsp_cmd, voA_osd_blend_enabled);
    mpi_cmd(dsp_cmd, voB_osd_blend_enabled);
    mpi_cmd(dsp_cmd, coded_bits_interrupt_enabled);
    mpi_cmd(dsp_cmd, pip_size_preview_enabled);
    mpi_cmd(dsp_cmd, low_delay_enabled);
    mpi_cmd(dsp_cmd, padding);
    mpi_cmd(dsp_cmd, sub_mode_sel.multiple_stream);
    mpi_cmd(dsp_cmd, sub_mode_sel.power_mode);
    mpi_cmd(dsp_cmd, num_yuv_src);
    mpi_cmd(dsp_cmd, resv_1);
    mpi_cmd(dsp_cmd, resv_2);
    mpi_cmd(dsp_cmd, audio_clk_freq);
    mpi_cmd(dsp_cmd, icore_freq);
    mpi_cmd(dsp_cmd, sensor_HB_pixel);
    mpi_cmd(dsp_cmd, sensor_VB_pixel);


    int ret = sgks_mpi_cmd_Send(&dsp_cmd, sizeof(sgks_dsp_cmd_system_setup_info_s));
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }


    return SGKS_SUCCESS;

}



inline void sgks_mpi_sys_buffer_size_roundup(int intlc_vi_intlc_enc, int encode_type, u16 origin_width, u16 origin_height, u16 *roundup_width, u16 *roundup_height)
{
    u16 round_h;

    if(intlc_vi_intlc_enc)
    {
        round_h = 32;
    }
    else
    {
        round_h    = 16;
    }

    if(encode_type == SGKS_ENCODE_H264)
    {
        *roundup_width  = ROUND_UP(origin_width, 16);
        *roundup_height = ROUND_UP(origin_height, round_h);
    }
    else
    {
        *roundup_width = origin_width;
        *roundup_height = origin_height;
    }
}



int sgks_mpi_sys_Cmd_VideoSystemSetup(sgks_mpi_manager_s *mpi)
{

    u16 max_w = 0, max_h = 0;
    int intlc_vi_intlc_enc = 0;    // Here we neglect the interlaced case, in favour of readability
    sgks_source_buffer_type_ex_t type;
    sgks_vi_src_capability_s vi_cap_ability[MAX_VI_NUM];
    sgks_vi_src_capability_s *current_vi_info  = NULL;

    int ret = sgks_mpi_vi_GetSensorCapability(vi_cap_ability);
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }

    current_vi_info = &vi_cap_ability[0];


    sgks_dsp_cmd_ipcam_video_system_setup_s  dsp_cmd;
    memset(&dsp_cmd, 0, sizeof(dsp_cmd));
    dsp_cmd.cmd_code 		= SGKS_DSP_CMD_IPCAM_VIDEO_SYSTEM_SETUP;
    dsp_cmd.cvbs_buf_nums 	= 3;

    sgks_mpi_sys_buffer_size_roundup(intlc_vi_intlc_enc
                                     ,SGKS_ENCODE_H264
                                     ,current_vi_info->cap_width
                                     ,current_vi_info->cap_height
                                     ,&max_w
                                     ,&max_h);


    dsp_cmd.main_max_width   = max_w;
    dsp_cmd.main_max_height  = max_h;


    ///////////////////////// preview_C_max /////////////////////////////////



    type = mpi->system_source_buff[SGKS_ENCODE_SOURCE_SECOND_BUFFER].type;

    switch(type)
    {

    case SGKS_SOURCE_BUFFER_TYPE_OFF:
        max_w = max_h = 0;
        break;

    case SGKS_SOURCE_BUFFER_TYPE_ENCODE:
        sgks_mpi_sys_buffer_size_roundup(intlc_vi_intlc_enc
                                         ,SGKS_ENCODE_H264
                                         ,mpi->system_resource.second_source_buffer_max_width
                                         ,mpi->system_resource.second_source_buffer_max_height
                                         ,&max_w
                                         ,&max_h);
        break;

    default:
        Printf("Invalid 2nd source buffer type [%d]!\n", type);
        return -1;

    }

    dsp_cmd.preview_C_max_width 	= max_w;
    dsp_cmd.preview_C_max_height 	= max_h;


    ////////////////////////// preview_B_max ////////////////////////////////


    type = mpi->system_source_buff[SGKS_ENCODE_SOURCE_THIRD_BUFFER].type;

    switch(type)
    {

    case SGKS_SOURCE_BUFFER_TYPE_OFF:
        max_w = max_h = 0;
        break;

    case SGKS_SOURCE_BUFFER_TYPE_ENCODE:
        sgks_mpi_sys_buffer_size_roundup(intlc_vi_intlc_enc
                                         ,SGKS_ENCODE_H264
                                         ,mpi->system_resource.third_source_buffer_max_width
                                         ,mpi->system_resource.third_source_buffer_max_height
                                         ,&max_w
                                         ,&max_h);
        break;

    case SGKS_SOURCE_BUFFER_TYPE_PREVIEW:
        max_w = mpi->preview_config.preview_info[SGKS_VO_PREVIEW_B].max_output_width;
        max_h = mpi->preview_config.preview_info[SGKS_VO_PREVIEW_B].max_output_height;
        break;

    default:
        Printf("Invalid 3rd source buffer type [%d]!\n", type);
        return -1;

    }

    dsp_cmd.preview_B_max_width  = max_w;
    dsp_cmd.preview_B_max_height = max_h;


    ///////////////////////////// preview_A_max //////////////////////////////////////////

    type = mpi->system_source_buff[SGKS_ENCODE_SOURCE_FOURTH_BUFFER].type;

    switch(type)
    {

    case SGKS_SOURCE_BUFFER_TYPE_OFF:
        max_w = max_h = 0;
        break;

    case SGKS_SOURCE_BUFFER_TYPE_ENCODE:
        sgks_mpi_sys_buffer_size_roundup(intlc_vi_intlc_enc
                                         ,SGKS_ENCODE_H264
                                         ,mpi->system_resource.fourth_source_buffer_max_width
                                         ,mpi->system_resource.fourth_source_buffer_max_height
                                         ,&max_w
                                         ,&max_h);
        break;

    case SGKS_SOURCE_BUFFER_TYPE_PREVIEW:
        max_w = mpi->preview_config.preview_info[SGKS_VO_PREVIEW_A].max_output_width;
        max_h = mpi->preview_config.preview_info[SGKS_VO_PREVIEW_A].max_output_height;
        break;

    default:
        Printf("Invalid 4th source buffer type [%d]!\n", type);
        return -1;

    }

    dsp_cmd.preview_A_max_width  = max_w;
    dsp_cmd.preview_A_max_height = max_h;

    ///////////////////////////////////////////////////////////////////


    dsp_cmd.stream_0_max_GOP_M = mpi->system_resource.stream_max_GOP_M[0];
    dsp_cmd.stream_1_max_GOP_M = mpi->system_resource.stream_max_GOP_M[1];
    dsp_cmd.stream_2_max_GOP_M = mpi->system_resource.stream_max_GOP_M[2];
    dsp_cmd.stream_3_max_GOP_M = mpi->system_resource.stream_max_GOP_M[3];
    dsp_cmd.stream_0_max_GOP_N = mpi->system_resource.stream_max_GOP_N[0];
    dsp_cmd.stream_1_max_GOP_N = mpi->system_resource.stream_max_GOP_N[1];
    dsp_cmd.stream_2_max_GOP_N = mpi->system_resource.stream_max_GOP_N[2];
    dsp_cmd.stream_3_max_GOP_N = mpi->system_resource.stream_max_GOP_N[3];




    dsp_cmd.stream_0_max_advanced_quality_model = mpi->system_resource.stream_max_advanced_quality_model[0];
    dsp_cmd.stream_1_max_advanced_quality_model = mpi->system_resource.stream_max_advanced_quality_model[1];
    dsp_cmd.stream_2_max_advanced_quality_model = mpi->system_resource.stream_max_advanced_quality_model[2];
    dsp_cmd.stream_3_max_advanced_quality_model = mpi->system_resource.stream_max_advanced_quality_model[3];



    ///////////////////////////////// stream_0_max //////////////////////////////////
    sgks_mpi_sys_buffer_size_roundup(intlc_vi_intlc_enc
                                     ,SGKS_ENCODE_H264
                                     ,current_vi_info->cap_width
                                     ,current_vi_info->cap_height
                                     ,&max_w
                                     ,&max_h);

    dsp_cmd.stream_0_max_width  = max_w;
    dsp_cmd.stream_0_max_height = max_h;



    ///////////////////////////////// stream_1_max //////////////////////////////////
    sgks_mpi_sys_buffer_size_roundup(intlc_vi_intlc_enc
                                     ,SGKS_ENCODE_H264
                                     ,mpi->system_resource.stream_max_encode_size[1].width
                                     ,mpi->system_resource.stream_max_encode_size[1].height
                                     ,&max_w
                                     ,&max_h);

    dsp_cmd.stream_1_max_width  = max_w;
    dsp_cmd.stream_1_max_height = max_h;




    ///////////////////////////////// stream_2_max //////////////////////////////////
    sgks_mpi_sys_buffer_size_roundup(intlc_vi_intlc_enc
                                     ,SGKS_ENCODE_H264
                                     ,mpi->system_resource.stream_max_encode_size[2].width
                                     ,mpi->system_resource.stream_max_encode_size[2].height
                                     ,&max_w
                                     ,&max_h);

    dsp_cmd.stream_2_max_width 	= max_w;
    dsp_cmd.stream_2_max_height = max_h;



    ///////////////////////////////// stream_3_max //////////////////////////////////
    sgks_mpi_sys_buffer_size_roundup(intlc_vi_intlc_enc
                                     ,SGKS_ENCODE_H264
                                     ,mpi->system_resource.stream_max_encode_size[3].width
                                     ,mpi->system_resource.stream_max_encode_size[3].height
                                     ,&max_w
                                     ,&max_h);

    dsp_cmd.stream_3_max_width  = max_w;
    dsp_cmd.stream_3_max_height = max_h;





    dsp_cmd.MCTF_possible 						= mpi->system_resource.MCTF_possible;
    dsp_cmd.max_num_streams 					= mpi->system_resource.max_num_encode_streams;
    dsp_cmd.max_num_cap_sources 				= mpi->system_resource.max_num_cap_sources;
    dsp_cmd.use_1Gb_DRAM_config 				= 1;
    dsp_cmd.raw_max_width 						= current_vi_info->cap_width;
    dsp_cmd.raw_max_height 						= current_vi_info->cap_height;
    dsp_cmd.temporal_filter_mode				= 0x2;



    mpi_cmd_hex(dsp_cmd, cmd_code);
    mpi_cmd(dsp_cmd, main_max_width);
    mpi_cmd(dsp_cmd, main_max_height);
    mpi_cmd(dsp_cmd, preview_A_max_width);
    mpi_cmd(dsp_cmd, preview_A_max_height);
    mpi_cmd(dsp_cmd, preview_B_max_width);
    mpi_cmd(dsp_cmd, preview_B_max_height);
    mpi_cmd(dsp_cmd, preview_C_max_width);
    mpi_cmd(dsp_cmd, preview_C_max_height);
    mpi_cmd(dsp_cmd, stream_0_max_GOP_M);
    mpi_cmd(dsp_cmd, stream_1_max_GOP_M);
    mpi_cmd(dsp_cmd, stream_2_max_GOP_M);
    mpi_cmd(dsp_cmd, stream_3_max_GOP_M);
    mpi_cmd(dsp_cmd, stream_0_max_GOP_N);
    mpi_cmd(dsp_cmd, stream_1_max_GOP_N);
    mpi_cmd(dsp_cmd, stream_2_max_GOP_N);
    mpi_cmd(dsp_cmd, stream_3_max_GOP_N);
    mpi_cmd(dsp_cmd, stream_0_max_advanced_quality_model);
    mpi_cmd(dsp_cmd, stream_1_max_advanced_quality_model);
    mpi_cmd(dsp_cmd, stream_2_max_advanced_quality_model);
    mpi_cmd(dsp_cmd, stream_3_max_advanced_quality_model);
    mpi_cmd(dsp_cmd, stream_0_max_width);
    mpi_cmd(dsp_cmd, stream_0_max_height);
    mpi_cmd(dsp_cmd, stream_1_max_width);
    mpi_cmd(dsp_cmd, stream_1_max_height);
    mpi_cmd(dsp_cmd, stream_2_max_width);
    mpi_cmd(dsp_cmd, stream_2_max_height);
    mpi_cmd(dsp_cmd, stream_3_max_width);
    mpi_cmd(dsp_cmd, stream_3_max_height);
    mpi_cmd(dsp_cmd, MCTF_possible);
    mpi_cmd(dsp_cmd, max_num_streams);
    mpi_cmd(dsp_cmd, max_num_cap_sources);
    mpi_cmd(dsp_cmd, use_1Gb_DRAM_config);
    mpi_cmd(dsp_cmd, cap_buf_cush);
    mpi_cmd(dsp_cmd, use_5_buffer);
    mpi_cmd(dsp_cmd, use_dsp_engine);
    mpi_cmd(dsp_cmd, temporal_filter_mode);
    mpi_cmd(dsp_cmd, cvbs_buf_nums);
    mpi_cmd(dsp_cmd, reserved2);
    mpi_cmd(dsp_cmd, raw_max_width);
    mpi_cmd(dsp_cmd, raw_max_height);

    ret = sgks_mpi_cmd_Send(&dsp_cmd, sizeof(sgks_dsp_cmd_ipcam_video_system_setup_s));
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }

    return SGKS_SUCCESS;

}




static int sgks_mpi_sys_Cmd_CHIP(sgks_mpi_manager_s *mpi)
{
    int ret = 0;
    sgks_dsp_cmd_chip_select_s dsp_cmd;
    memset(&dsp_cmd, 0, sizeof(dsp_cmd));
    dsp_cmd.cmd_code  = SGKS_DSP_CMD_CHIP_SELECTION;
    dsp_cmd.chip_type = 3;

    if (sgks_mpi_cmd_Send(&dsp_cmd, sizeof(sgks_dsp_cmd_chip_select_s)) != SGKS_SUCCESS)
    {
        return SGKS_ERR_SYS_FWCMDSENDERR;
    }

    return SGKS_SUCCESS;
}


int sgks_mpi_sys_setup_Info()
{


    return SGKS_SUCCESS;
}


int sgks_mpi_sys_ClearIRQ(sgks_mpi_manager_s *mpi)
{

    u8 *msg_buf = NULL;

    SGKS_MDI_DRV_BUFF(msg_buf);
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_CLEARUPIRQ, 0, 0, SGKS_ERR_SYS_DRIVERIOCTLERR);

    return SGKS_SUCCESS;
}

int sgks_mpi_sys_SetupIRQ(sgks_mpi_manager_s *mpi)
{

    u8 *msg_buf = NULL;

    SGKS_MDI_DRV_BUFF(msg_buf);
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_SETUPIRQ, 0, 0, SGKS_ERR_SYS_DRIVERIOCTLERR);

    return SGKS_SUCCESS;
}


static int sgks_mpi_sys_cmd_RgbToYuvDefaultSetup(sgks_mpi_manager_s *mpi)
{
    CHECK_POINT_NULL_RETURN(mpi, SGKS_FAIL);

    sgks_dsp_cmd_rgb_to_yuv_setup_s dsp_cmd;
    sgks_vi_src_capability_s vi_cap_ability[MAX_VI_NUM];

    sgks_source_buffer_format_ex_t *main_format = &mpi->system_source_buff[0].format;

    int ret = sgks_mpi_vi_GetSensorCapability(vi_cap_ability);
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }

    sgks_vi_src_capability_s *current_vi_info = &vi_cap_ability[0];


    // if not RAW, do nothing
    if(current_vi_info->input_format)
    {
        return SGKS_FAIL;
    }

    memset(&dsp_cmd, 0, sizeof(dsp_cmd));

    dsp_cmd.cmd_code 				= SGKS_DSP_CMD_RGB_TO_YUV_SETUP;
    dsp_cmd.matrix_values[0] 		= 0xBB;
    dsp_cmd.matrix_values[1] 		= 0x275;
    dsp_cmd.matrix_values[2] 		= 0x3F;
    dsp_cmd.matrix_values[3] 		= 0xFF99;
    dsp_cmd.matrix_values[4] 		= 0xFEA6;
    dsp_cmd.matrix_values[5] 		= 0x1C2;
    dsp_cmd.matrix_values[6] 		= 0x1C2;
    dsp_cmd.matrix_values[7] 		= 0xFE67;
    dsp_cmd.matrix_values[8] 		= 0xFFD7;
    dsp_cmd.y_offset 				= 0x0;
    dsp_cmd.u_offset 				= 0x80;
    dsp_cmd.v_offset 				= 0x80;

    mpi_cmd_hex(dsp_cmd, cmd_code);
    mpi_cmd_hex(dsp_cmd, matrix_values[0]);
    mpi_cmd_hex(dsp_cmd, matrix_values[1]);
    mpi_cmd_hex(dsp_cmd, matrix_values[2]);
    mpi_cmd_hex(dsp_cmd, matrix_values[3]);
    mpi_cmd_hex(dsp_cmd, matrix_values[4]);
    mpi_cmd_hex(dsp_cmd, matrix_values[5]);
    mpi_cmd_hex(dsp_cmd, matrix_values[6]);
    mpi_cmd_hex(dsp_cmd, matrix_values[7]);
    mpi_cmd_hex(dsp_cmd, matrix_values[8]);
    mpi_cmd_hex(dsp_cmd, y_offset);
    mpi_cmd_hex(dsp_cmd, u_offset);
    mpi_cmd_hex(dsp_cmd, v_offset);

    ret = sgks_mpi_cmd_Send(&dsp_cmd, sizeof(sgks_dsp_cmd_system_setup_info_s));
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }

    return SGKS_SUCCESS;

}


void sgks_mpi_sys_ResetDSP(void)
{

    u8 *msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);

    sgks_mdi_reg_rw_s *reg = msg_buf;
    reg->reg_num =1;

    reg->reg_info[0].addr 			= 0xf111ff00;
    reg->reg_info[0].addr_type   	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    reg->reg_info[0].val  		 	= 0x000000FF;


    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_REG_WRITE, 0, sizeof(sgks_mdi_reg_rw_s), SGKS_ERR_SYS_DRIVERIOCTLERR);


}



int sgks_mpi_sys_SendDefaultCmd(sgks_mpi_manager_s *mpi)
{

    sgks_mpi_dsp_status_s dsp_status;
    memset(&dsp_status, 0, sizeof(sgks_mpi_dsp_status_s));
    sgks_mpi_sys_GetDspStats(&dsp_status);

    Printf("[send default cmd] dsp_state.op_mode 0x%x,dsp_state.state 0x%x\n",dsp_status.op_mode,dsp_status.state);

    sgks_mpi_cmd_SetMode(mpi, SGKS_MDI_CMD_MODE_DEFAULT_LOADING);

    if (dsp_status.op_mode == SGKS_DSP_DECODE_MODE)
    {

        sgks_mpi_sys_Cmd_CHIP(mpi);

        sgks_mpi_vi_Cmd_CapWin(mpi);

        sgks_mpi_sys_Cmd_SetupInfo(mpi);

        sgks_mpi_vo_Cmd(mpi,SGKS_VIDEO_VOUT_SW);

        sgks_mpi_vi_Cmd_VideoPreProc(mpi);//--->sys

        sgks_vi_Cmd_SensorConfig(mpi);

        sgks_mpi_sys_Cmd_VideoSystemSetup(mpi);

        sgks_mpi_sys_cmd_CapturePreviewBufferSetup(mpi);

        sgks_mpi_sys_cmd_RgbToYuvDefaultSetup(mpi);

        sgks_mpi_sys_cmd_RgbGainDefault(mpi);

    }
    else
    {

    sgks_mpi_sys_Cmd_CHIP(mpi);

    sgks_mpi_vi_Cmd_CapWin(mpi);

    sgks_mpi_sys_Cmd_SetupInfo(mpi);

    sgks_mpi_vo_Cmd(mpi,SGKS_VIDEO_VOUT_SW);

    sgks_mpi_vi_Cmd_VideoPreProc(mpi);//--->sys

    sgks_vi_Cmd_SensorConfig(mpi);

    sgks_mpi_sys_Cmd_VideoSystemSetup(mpi);

    sgks_mpi_sys_cmd_CapturePreviewBufferSetup(mpi);

        sgks_mpi_sys_cmd_RgbGainDefault(mpi);

    }


    u8 *msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);
    sgks_mdi_opt_d_cache_s *cache		= msg_buf;
    cache->cache_type                	= SGKS_OPT_D_CACHE_CLAEN;
    cache->start                     	= mpi->mpi_init_param.dsp_init_param.default_config_ptr_phy;
    cache->size                      	= mpi->mpi_init_param.dsp_init_param.default_config_size;
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_OPT_D_CACHE, 0, sizeof(sgks_mdi_opt_d_cache_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

    sgks_mpi_cmd_SetMode(mpi, SGKS_MDI_CMD_MODE_DEFAULT_READY);

    return SGKS_SUCCESS;

}


int sgks_mpi_sys_BootFw(sgks_mpi_manager_s *mpi)
{

#if 0

#define AUDIO_REG_BASE   (0x80000000)
#define MAP_SIZE        0x800000
    int  dev_fd = open("/dev/mem", O_RDWR | O_NDELAY);

    if (dev_fd < 0)
    {
        printf("open(/dev/mem) failed.");
        return 0;
    }

    unsigned char *map_base=(unsigned char * )mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, AUDIO_REG_BASE);



    printf("test %x \n", *(volatile unsigned int *)(map_base+0x150000));

    *(volatile unsigned int *)(map_base + 0x150000) = 0x80000000;
    *(volatile unsigned int *)(map_base + 0x160000) = 0x80000000;
    *(volatile unsigned int *)(map_base + 0x15000c) = 0x07;
    *(volatile unsigned int *)(map_base + 0x160008) = 0xc0020000;
    *(volatile unsigned int *)(map_base + 0x150008) = 0xc0220000;
    *(volatile unsigned int *)(map_base + 0x150000) = 0x0000000F;
    *(volatile unsigned int *)(map_base + 0x150000) = 0x0000000F;

    printf("22 %x \n", *(volatile unsigned int *)(map_base+0x150000));
    if(dev_fd)
        close(dev_fd);

    munmap(map_base,MAP_SIZE); 


#else
    u8 *msg_buf = NULL;

    SGKS_MDI_DRV_BUFF(msg_buf);



    sgks_mdi_reg_rw_s *reg = msg_buf;
    reg->reg_num =7;

    reg->reg_info[0].addr 			= 0xf1150000;
    reg->reg_info[0].addr_type   	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    reg->reg_info[0].val  		 	= 0x80000000;

    reg->reg_info[1].addr 			= 0xf1160000;
    reg->reg_info[1].addr_type  	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    reg->reg_info[1].val  			= 0x80000000;

    reg->reg_info[2].addr 			= 0xf115000c;
    reg->reg_info[2].addr_type  	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    reg->reg_info[2].val  			= 0x07;

    reg->reg_info[3].addr 			= 0xf1160008;
    reg->reg_info[3].addr_type  	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    reg->reg_info[3].val  			= 0xc0020000;

    reg->reg_info[4].addr 			= 0xf1150008;
    reg->reg_info[4].addr_type  	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    reg->reg_info[4].val  			= 0xc0220000;

    reg->reg_info[5].addr 			= 0xf1150000;
    reg->reg_info[5].addr_type  	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    reg->reg_info[5].val  			= 0x0000000F;

    reg->reg_info[6].addr 			= 0xf1160000;
    reg->reg_info[6].addr_type  	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    reg->reg_info[6].val  			= 0x0000000F;

    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_REG_WRITE, 0, sizeof(sgks_mdi_reg_rw_s), SGKS_ERR_SYS_DRIVERIOCTLERR);
#endif

    sgks_mpi_dsp_status_s dsp_status;
    dsp_status.op_mode  	= mpi->mpi_init_param.dsp_init_param.operation_mode;
    dsp_status.op_sub_mode	= -1;
    dsp_status.state    	= -1;

    int ret = sgks_mpi_sys_WaitDspStats(&dsp_status);
    if (ret != SGKS_SUCCESS)
        return ret;

    sgks_mpi_cmd_SetMode(mpi, SGKS_MDI_CMD_MODE_NORMAL_LOADING);


    Printf("==== sgks_mpi_sys_BootFw ok\n");


    return SGKS_SUCCESS;



}


int sgks_mpi_sys_ReadFileToMem(char *filename, u8 *addr, u32 size)
{
    FILE *fp = NULL;


    if((fp = fopen(filename, "rb")) == NULL)
    {
        ERR_PRINT("open failed.\n");
        return SGKS_ERR_SYS_OPENFWFILEFAIL;
    }

    if(fread(addr, 1, size, fp) != size)
    {
        fclose(fp);
        ERR_PRINT("fread failed\n");
        return SGKS_ERR_SYS_READFWFILEFAIL;
    }

    fclose(fp);

}


int sgks_mpi_sys_DumpMemToFile(char *filename, u8 *addr, u32 size)
{
    FILE *fp = NULL;


    if((fp = fopen(filename, "w")) == NULL)
    {
        ERR_PRINT("open failed.\n");
        return SGKS_ERR_SYS_OPENFWFILEFAIL;
    }

    if(fwrite(addr, 1, size, fp) != size)
    {
        fclose(fp);
        ERR_PRINT("fwrite failed\n");
        return SGKS_ERR_SYS_READFWFILEFAIL;
    }

    fclose(fp);

}



int sgks_mpi_sys_Start()
{
    int ret = 0;
    sgks_mpi_manager_s *mpi = mpi_get_managerHanle();

    ret = sgks_mpi_isp_SetMpiToIspHandle(mpi);
    if (ret != SGKS_SUCCESS)
    {
        Printf("err:isp_SetMpiToIspHandle , nRet=%d\n", ret);
        return SGKS_ERR_ISP_INIT_FAIL;
    }

    ret = sgks_mpi_sys_SetupIRQ(mpi);
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }

    if (mpi->mpi_init_param.dsp_init_param.operation_mode == SGKS_DSP_ENCODE_MODE)
    {
        ret = sgks_mpi_sys_SendDefaultCmd(mpi);
        if (ret != SGKS_SUCCESS)
        {
            return ret;
        }
    }

    ret = sgks_mpi_sys_BootFw(mpi);
    if (ret != SGKS_SUCCESS)
    {
        return ret;
    }

    if (mpi->mpi_init_param.dsp_init_param.operation_mode == SGKS_DSP_ENCODE_MODE)
    {
        ret = sgks_mpi_isp_start(mpi);
        if (ret != SGKS_SUCCESS)
        {
            return ret;
        }
    }

    return SGKS_SUCCESS;
}


static int sgks_mpi_sys_CheckMemAddrPageAlign(sgks_mpi_init_s *mpi_init_param)
{

    int i = 0;

    u8 *msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_GETPAGESIZE, 0, sizeof(sgks_get_pagesize_s), SGKS_ERR_SYS_DRIVERIOCTLERR);
    sgks_get_pagesize_s *kernel_page = msg_buf;
    u32 page_size = kernel_page->page_size;


    for (i=0; i<mpi_init_param->fw_info.fw_file_num; i++)
    {
        SGKS_MPI_CHECK_MEM_PAGE_ALIGN((u32)mpi_init_param->fw_info.code_addr[i].dsp_code_start, page_size, SGKS_ERR_SYS_INITMEMPARAMFAIL);
    }


    SGKS_MPI_CHECK_MEM_PAGE_ALIGN((u32)mpi_init_param->dsp_init_param.dsp_init_data_phy, 				page_size, SGKS_ERR_SYS_INITMEMPARAMFAIL);
    SGKS_MPI_CHECK_MEM_PAGE_ALIGN((u32)mpi_init_param->dsp_init_param.default_binary_data_ptr_phy,		page_size, SGKS_ERR_SYS_INITMEMPARAMFAIL);
    SGKS_MPI_CHECK_MEM_PAGE_ALIGN((u32)mpi_init_param->dsp_init_param.default_config_ptr_phy, 			page_size, SGKS_ERR_SYS_INITMEMPARAMFAIL);
    SGKS_MPI_CHECK_MEM_PAGE_ALIGN((u32)mpi_init_param->dsp_init_param.cmd_data_ptr_phy, 				page_size, SGKS_ERR_SYS_INITMEMPARAMFAIL);
    SGKS_MPI_CHECK_MEM_PAGE_ALIGN((u32)mpi_init_param->dsp_init_param.result_queue_ptr_phy, 			page_size, SGKS_ERR_SYS_INITMEMPARAMFAIL);
    SGKS_MPI_CHECK_MEM_PAGE_ALIGN((u32)mpi_init_param->dsp_init_param.dram_print_buf_addr_phy, 		page_size, SGKS_ERR_SYS_INITMEMPARAMFAIL);
    SGKS_MPI_CHECK_MEM_PAGE_ALIGN((u32)mpi_init_param->dsp_init_param.dsp2_info_ptr_phy, 				page_size, SGKS_ERR_SYS_INITMEMPARAMFAIL);
    SGKS_MPI_CHECK_MEM_PAGE_ALIGN((u32)mpi_init_param->dsp_init_param.chip_id_ptr_phy, 				page_size, SGKS_ERR_SYS_INITMEMPARAMFAIL);
    SGKS_MPI_CHECK_MEM_PAGE_ALIGN((u32)mpi_init_param->dsp_init_param.DSP_buf_ptr_phy, 				page_size, SGKS_ERR_SYS_INITMEMPARAMFAIL);
    SGKS_MPI_CHECK_MEM_PAGE_ALIGN((u32)mpi_init_param->dsp_init_param.msg_addr_arm_osd_phy, 			page_size, SGKS_ERR_SYS_INITMEMPARAMFAIL);

    return SGKS_SUCCESS;

}


int sgks_mpi_sys_DelShareMem(sgks_mpi_manager_s *mpi)
{

	int share_mem_id = mpi->shm_id;

    if(shmdt(mpi) == -1)  
    {  
        Printf("shmdt failed\n");  
        return SGKS_FAIL;  
    }  
     
    if(shmctl(share_mem_id, IPC_RMID, 0) == -1)  
    {  
        Printf("shmctl(IPC_RMID) failed\n");  
        return SGKS_FAIL;  
    }  

    Printf("sys DelShareMem ok\n");  
	
    return SGKS_SUCCESS;

}

int sgks_mpi_sys_GetShareMem(int shm_id,  u8 **shm_p)
{

    int shmid = shmget(shm_id, 0, 0);
    if (shmid == -1)
    {
        //perror("shmget err");
        return SGKS_ERR_SYS_SHMGETERR;
    }

    u8 *p = shmat(shmid, NULL, 0);
    if (p == (void *)-1 )
    {
        //perror("shmget err");
        return SGKS_ERR_SYS_SHMGETERR;
    }

    *shm_p = p;

    return SGKS_SUCCESS;

}


int sgks_mpi_sys_CreateShareMem(int *shm_id, key_t key, u8 **shm_ptr, int size)
{

    Printf("Create Shar eMem\n");

    int shmid;
    shmid = shmget(key, size, IPC_CREAT | 0666);
    if (shmid == -1)
    {
        perror("shmget err");
        return SGKS_ERR_SYS_SHMCREATEERR;
    }

    u8 *p = shmat(shmid, NULL, 0);
    if (p == (void *)-1)
    {
        perror("shmget err");
        return SGKS_ERR_SYS_SHMCREATEERR;
    }

    *shm_id 	= shmid;
    *shm_ptr  	= p;

    return SGKS_SUCCESS;

}


int sgks_mpi_sys_GetModuleInitStatus(sgks_mpi_manager_s *mpi, sgks_mpi_module_id_e module_id)
{

    CHECK_POINT_NULL_RETURN(mpi, SGKS_FAIL);

    return 	(mpi->mpi_module_initStatus >> module_id) & 0x1;

}


int sgks_mpi_sys_UpdateModuleInitStatus(sgks_mpi_manager_s *mpi, sgks_mpi_module_id_e module_id, sgks_mpi_module_init_status_e module_status)
{
    CHECK_POINT_NULL_RETURN(mpi, SGKS_FAIL);

    if (module_status == MPI_MODULE_STATUS_INIT)
        mpi->mpi_module_initStatus |= (0x1 << module_id);
    else if (module_status == MPI_MODULE_STATUS_NOINIT)
        mpi->mpi_module_initStatus &= (~(0x1 << module_id));

    return SGKS_SUCCESS;

}

int sgks_mpi_sys_UpdateBsbAddr(sgks_mpi_manager_s *mpi)
{
    CHECK_POINT_NULL_RETURN(mpi,SGKS_FAIL);

    sgks_default_enc_binary_data_s *enc_binary_data = NULL;
    dsp_code_addr_s *binary_code_addr  = &(mpi->mpi_init_param.fw_info.code_addr[2]);
    u8 *msg_buf = NULL;

    SGKS_MDI_DRV_BUFF(msg_buf);
    sgks_mdi_mmap_s *mmap_info = msg_buf;

    mmap_info->mmap_phy_start_addr = binary_code_addr->dsp_code_start;
    mmap_info->mmap_phy_size       = binary_code_addr->dsp_code_size;
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_MMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

    if (mmap_info->mmap_user_size == binary_code_addr->dsp_code_size && mmap_info->mmap_user_start_addr != NULL)
    {
        enc_binary_data = (sgks_default_enc_binary_data_s *)mmap_info->mmap_user_start_addr;
    }

    enc_binary_data->dram_addr_cabac_out_bit_buffer = mpi->mpi_init_param.dsp_init_param.bsb_phy;
    enc_binary_data->dram_addr_jpeg_out_bit_buffer = mpi->mpi_init_param.dsp_init_param.bsb_phy;
    enc_binary_data->h264_out_bit_buf_sz = mpi->mpi_init_param.dsp_init_param.bsb_size;
    enc_binary_data->jpeg_out_bit_buf_sz = mpi->mpi_init_param.dsp_init_param.bsb_size;
    enc_binary_data->dram_addr_bit_info_buffer = mpi->mpi_init_param.dsp_init_param.bsb_desc_phy;
    enc_binary_data->bit_info_buf_sz =  mpi->mpi_init_param.dsp_init_param.bsb_desc_size;

    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_UNMMAP, 0, sizeof(sgks_mdi_mmap_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

    SGKS_MDI_DRV_CLEAN_DATABUFF();
    sgks_mdi_opt_d_cache_s *cache  = msg_buf;
    cache->cache_type                   = SGKS_OPT_D_CACHE_CLAEN;
    cache->start                        = binary_code_addr->dsp_code_start;
    cache->size                         = sizeof(sgks_default_enc_binary_data_s);
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_OPT_D_CACHE, 0, sizeof(sgks_mdi_opt_d_cache_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

    return SGKS_SUCCESS;
}

int sgks_mpi_sys_GetMpiHandle()
{

    int ret    						= -1;
    int shm_id 						= -1;
    u8  *shm_ptr 				  	= NULL;
    sgks_mpi_manager_s **shm_mpi 	= NULL;


    /************get mpi share mem**************/
    ret = sgks_mpi_sys_GetShareMem(MPI_HANDLE_SHMID, &shm_ptr);

    if (ret != SGKS_SUCCESS)
    {
        ret = sgks_mpi_sys_CreateShareMem(&shm_id, MPI_HANDLE_SHMID, &shm_ptr, sizeof(sgks_mpi_manager_s));
        if (ret != SGKS_SUCCESS)
            return ret;
		
		memset(shm_ptr, 0, sizeof(sgks_mpi_manager_s));

	}

    /************update mpi area**************/
    shm_mpi 	= mpi_get_managerHanleAddr();
    *shm_mpi 	= (sgks_mpi_manager_s *)shm_ptr;


    /************update mpi shm_id**************/
    sgks_mpi_manager_s *mpi 	= mpi_get_managerHanle();
    mpi->shm_id 			   	= shm_id;


    return SGKS_SUCCESS;

}



int sgks_mpi_sys_LoseMpiHandle(sgks_mpi_manager_s *mpi)
{
	
    int ret = sgks_mpi_sys_DelShareMem(mpi);
		if (ret != SGKS_SUCCESS)
			return ret;
		
    return SGKS_SUCCESS;

}

int sgks_mpi_sys_ReleaseMdiResource(sgks_mpi_manager_s *mpi)
{

	int ret = -1;
	
	ret = sgks_mpi_sys_ClearIRQ(mpi);

	if (ret != SGKS_SUCCESS)
        return ret;

	return SGKS_SUCCESS;

}




int sgks_mpi_sys_Init(sgks_mpi_init_s *mpi_init_param)
{

    CHECK_POINT_NULL_RETURN(mpi_init_param,SGKS_FAIL);

    int ret    						= -1;

	printf("**********************************************************************\n");
	printf("* sgks libmpi svn version: %s  build time: %s  \r\n",SVNREVISION,TIMESTAMP);
	printf("**********************************************************************\n");


    /**************************/
    ret = sgks_mpi_sys_GetMpiHandle();
    if (ret != SGKS_SUCCESS)
        return ret;

    /**************************/
    sgks_mpi_manager_s *mpi = mpi_get_managerHanle();

    if (sgks_mpi_sys_GetModuleInitStatus(mpi ,MPI_MODULE_SYS_ID) == MPI_MODULE_STATUS_INIT)
    {
        Printf("sgks_mpi_sys already init\n");
        return SGKS_SUCCESS;
    }

    mpi->curr_module_id		= MPI_MODULE_SYS_ID;

    mpi->isp_init_param.enable = 0;

    ret = sgks_mpi_sys_GetDriverHandle(mpi);
    if (ret != SGKS_SUCCESS)
        return ret;

    ret = sgks_mpi_sys_CheckMemAddrPageAlign(mpi_init_param);
    if (ret != SGKS_SUCCESS)
        return ret;

    memcpy(&mpi->mpi_init_param, mpi_init_param, sizeof(sgks_mpi_init_s));


    ret = sgks_mpi_sys_LoadFw(mpi);
    if (ret != SGKS_SUCCESS)
        return ret;

    ret = sgks_mpi_sys_InitFwParam(mpi);
    if (ret != SGKS_SUCCESS)
        return ret;

    ret = sgks_mpi_sys_initParam(mpi);
    if (ret != SGKS_SUCCESS)
        return ret;

    ret = sgks_mpi_sys_SetDspBuffer(mpi);
    if (ret != SGKS_SUCCESS)
        return ret;

    ret = sgks_mpi_sys_UpdateBsbAddr(mpi);
    if (ret != SGKS_SUCCESS)
        return ret;

    sgks_mpi_sys_UpdateModuleInitStatus(mpi, MPI_MODULE_SYS_ID, MPI_MODULE_STATUS_INIT);

    Printf("sgks_mpi_sys_Init ok!\n");

    return SGKS_SUCCESS;

}


int sgks_mpi_sys_PreViewInit(sgks_preview_config_s *preview_config)
{
    sgks_mpi_manager_s *mpi = mpi_get_managerHanle();

    memcpy(&mpi->preview_config, preview_config, sizeof(sgks_preview_config_s));

    return SGKS_SUCCESS;
}




int sgks_mpi_sys_MallcKMem(sgks_mpi_mem_s *meminfo, u32 size)
{
    msg_t ioctl_msg;

    if(meminfo == NULL)
    {
        Printf("Error: parameter null\n");
        return SGKS_ERR_SYS_PARAMERR;
    }
    meminfo->size = size;
    memset(&ioctl_msg, 0, sizeof(ioctl_msg));
    ioctl_msg.msg_head.msg_type = SGKS_MDI_OPERATION_MALLOC;
    ioctl_msg.msg_head.msg_size = sizeof(sgks_mdi_mem_s);
    memcpy(ioctl_msg.msg_data, meminfo, sizeof(sgks_mdi_mem_s));
    if(ioctl(mpi_get_managerHanle()->driver_handle, SGKS_MDI_IOCTL_OPERATION, &ioctl_msg) < 0)
    {
        Printf("ioctl msg send err.\n");
        return SGKS_ERR_SYS_MALLOCERR;
    }
    memcpy(meminfo, ioctl_msg.msg_data, sizeof(sgks_mdi_mem_s));

    return SGKS_SUCCESS;
}

int sgks_mpi_sys_FreeKMem(sgks_mpi_mem_s *meminfo)
{
    msg_t ioctl_msg;

    if(meminfo == NULL)
    {
        Printf("Error: parameter null\n");
        return SGKS_ERR_SYS_PARAMERR;
    }

    memset(&ioctl_msg, 0, sizeof(ioctl_msg));
    ioctl_msg.msg_head.msg_type = SGKS_MDI_OPERATION_FREE;
    ioctl_msg.msg_head.msg_size = sizeof(sgks_mdi_mem_s);
    memcpy(ioctl_msg.msg_data, meminfo, sizeof(sgks_mdi_mem_s));
    if(ioctl(mpi_get_managerHanle()->driver_handle, SGKS_MDI_IOCTL_OPERATION, &ioctl_msg) < 0)
    {
        Printf("ioctl msg send err.\n");
        return SGKS_ERR_SYS_FREEERR;
    }

    return SGKS_SUCCESS;
}


inline int sgks_mpi_sys_ConfigCvbsDma(int en)
{
    return 0;
    u8* msg_buf = NULL;
    SGKS_MDI_DRV_BUFF(msg_buf);
    sgks_mdi_reg_rw_s *reg = msg_buf;

    reg->reg_num 				= 1;
    reg->reg_info[0].addr      	= 0xf0020400;
    reg->reg_info[0].addr_type 	= SGKS_MDI_REG_ADDR_TYPE_VIR;
    SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_REG_READ, 0, sizeof(sgks_mdi_reg_rw_s), SGKS_ERR_SYS_DRIVERIOCTLERR);

    if(en == 1)
    {

        reg->reg_info[0].val      |= 0x1;
        reg->reg_info[0].delay_ms = 0;
        Printf("sgks_mpi_sys_ConfigCvbsDma 1 addr 0x%x, val 0x%x\n",reg->reg_info[0].addr,reg->reg_info[0].val);
        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_REG_WRITE, 0, sizeof(sgks_mdi_reg_rw_s), SGKS_ERR_SYS_DRIVERIOCTLERR);
    }
    else
    {

        reg->reg_info[0].val      &=  0xFFFFFFFE;
        reg->reg_info[0].delay_ms = 0;
        Printf("sgks_mpi_sys_ConfigCvbsDma 0 addr 0x%x, val 0x%x\n",reg->reg_info[0].addr,reg->reg_info[0].val);
        SGKS_MDI_DRV_IOCTL(SGKS_MDI_OPERATION_REG_WRITE, 0, sizeof(sgks_mdi_reg_rw_s), SGKS_ERR_SYS_DRIVERIOCTLERR);
    }

    return SGKS_SUCCESS;

}


int sgks_mpi_sys_DeInit()
{
    sgks_mpi_manager_s *mpi = mpi_get_managerHanle();

	int ret = sgks_mpi_sys_LoseDriverHandle(mpi);
    if (ret != SGKS_SUCCESS)
        return ret;

	ret = sgks_mpi_sys_ReleaseMdiResource(mpi);
    if (ret != SGKS_SUCCESS)
        return ret;

	ret = sgks_mpi_sys_LoseMpiHandle(mpi);
    if (ret != SGKS_SUCCESS)
        return ret;

    return SGKS_SUCCESS;

}



